package com.meaningful.thinking.thread_pool_demo;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class MyThreadPool {

    private final int coreSize;
    private final int maxSize;
    private final int timeout;
    private final TimeUnit timeUnit;
    // 具体的执业务行逻辑的地方
    // 阻塞队列是防止CPU空转
    private final BlockingQueue<Runnable> commandList;
    // 拒绝策略
    private final RejectHandle rejectHandle;

    public MyThreadPool(
            int coreSize,
            int maxSize,
            int timeout,
            TimeUnit timeUnit,
            BlockingQueue<Runnable> commandList,
            RejectHandle rejectHandle
    ) {
        this.coreSize = coreSize;
        this.maxSize = maxSize;
        this.timeout = timeout;
        this.timeUnit = timeUnit;
        this.commandList = commandList;
        this.rejectHandle = rejectHandle;
    }

    // 线程池是否已关闭
    private volatile boolean isShutdown = false;

    // 核心线程容器
    List<Thread> coreList = new ArrayList<>();

    // 辅助线程容器
    List<Thread> supportList = new ArrayList<>();

    public BlockingQueue<Runnable> getCommandList() {
        return commandList;
    }

    // 1. 对应的线程什么时候创建
    //  需要注意的是创建线程资源是十分消耗资源的，所以做好重复利用创建好的线程
    //  线程执行完毕后会自动销毁
    // 2. 现成的runnables是什么？是我们提交的command吗？
    // 3. 以下操作例如判断县城容器长度、添加线程进入容器都不是原子操作，会出现并发安全问题
    void execute(Runnable command) {
        synchronized (MyThreadPool.class) {
            // 判断threadList有多少个元素，看看是否满足核心线程数
            if (coreList.size() < coreSize) {
                Thread thread = new CoreThread();
                coreList.add(thread);
                thread.start();
            }
            // 无法添加任务，证明阻塞队列满了，需要处理额外的任务,使用辅助线程或其他策略
            boolean offer = commandList.offer(command);
            if (offer) {
                return;
            }
            // 走到这一步标识业务逻辑没有添加到阻塞队列，启动的辅助线程不一定执行当前的业务逻辑
            // 判断辅助线程是否已满,没有满就尝试创建
            if (coreList.size() + supportList.size() < maxSize) {
                Thread thread = new SupportThread();
                supportList.add(thread);
                thread.start();
            }
        }
        // 再次尝试塞入阻塞队列
        if (!commandList.offer(command)) {
            // 到这一步的话阻塞队列确实满了
            System.out.println("阻塞队列满了！");
            rejectHandle.rejected(command, this);
        }
    }

    public void shutdown() {
        isShutdown = true;
        // 中断所有核心线程和辅助线程
        coreList.forEach(Thread::interrupt);
        supportList.forEach(Thread::interrupt);
    }

    class CoreThread extends Thread {

        // 固定线程名前缀（建议用常量）
        private static final String THREAD_NAME_PREFIX = "CoreThread-";

        private static final AtomicInteger threadCounter = new AtomicInteger(1);

        public CoreThread() {
            // 默认构造方法：前缀 + 自增编号（如 "SupportThread-1"）
            super(THREAD_NAME_PREFIX + threadCounter.getAndIncrement());
        }

        public CoreThread(String customSuffix) {
            // 允许自定义后缀（如 "SupportThread-OrderTask"）
            super(THREAD_NAME_PREFIX + customSuffix);
        }

        @Override
        public void run() {
            while (true) {
                try {
                    Runnable command = commandList.take();
                    command.run();
                } catch (InterruptedException e) {
                    // 响应中断，退出循环
                    if (isShutdown) {
                        System.out.println(getName() + " 核心线程退出");
                        break;
                    }
                }
            }
        }

    }

    class SupportThread extends Thread {

        // 固定线程名前缀（建议用常量）
        private static final String THREAD_NAME_PREFIX = "SupportThread-";

        private static final AtomicInteger threadCounter = new AtomicInteger(1);

        public SupportThread() {
            // 默认构造方法：前缀 + 自增编号（如 "SupportThread-1"）
            super(THREAD_NAME_PREFIX + threadCounter.getAndIncrement());
        }

        public SupportThread(String customSuffix) {
            // 允许自定义后缀（如 "SupportThread-OrderTask"）
            super(THREAD_NAME_PREFIX + customSuffix);
        }

        @Override
        public void run() {
            while (true) {
                try {
                    // 需要设定超时时间，如果超过超时时间就释放线程资源
                    Runnable command = commandList.poll(timeout, timeUnit);
                    if (Objects.isNull(command)) {
                        // 移除辅助线程
                        supportList.remove(this);
                        break;
                    }
                    command.run();
                } catch (InterruptedException e) {
                    if (isShutdown) {
                        System.out.println(getName() + " 辅助线程退出");
                        break;
                    }
                }
            }
            System.out.println(Thread.currentThread().getName() + "辅助线程资源释放");
        }
    }

}
